import { createAlova } from 'alova';
import AdapterTaro, { taroRequestAdapter } from '@alova/adapter-taro';
import { useTokenStore } from '@/stores/useTokenStore';
import ReactHook from 'alova/react';
import Taro from '@tarojs/taro';
import utils from '@/utils'
import { Session } from '#/entity'
// 实时日志
const logManager = Taro.getRealtimeLogManager()
//判断是否是生产环境
const isProduction = process.env.NODE_ENV === 'production';
// 获取版本号
const systemInfo: any = Taro.getSystemInfoSync()
let version = '-.-.-'
if (systemInfo && systemInfo.miniProgram && systemInfo.miniProgram.version) {
  version = systemInfo.miniProgram.version
}


const baseConfig = {
  // 默认地址请求地址，可在 .env.** 文件中修改
  baseURL: process.env.TARO_APP_BASE_URL,
  // 设置请求头
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
    'Accept': 'application/json',
    'X-Requested-With': 'Hiwie-Fetch'
  }
};
// 这儿排除掉一些接口，防重复提交
const excludeList = [
  'session',
]

type TMeta = {
  loading?: boolean,
  isHideToastMsg?: boolean
}
const _loading = () => {
  Taro.showLoading({
    title: "加载中"
  })
}
const _hideLoading = (meta: TMeta) => {
  // if (!meta.loading) return
  Taro.hideLoading()
}

const _showMsg = (msg: string, isHideToastMsg = false) => {
  if (isHideToastMsg) return
  // utils.$toast(msg)
  Taro.showToast({
    title: msg,
    icon: 'none',
    duration: 2000
  })
}

const alovaInst = createAlova({
  ...baseConfig,
  ...AdapterTaro(),
  statesHook: ReactHook,
  requestAdapter: taroRequestAdapter,
  async beforeRequest(method) {

    const cookie = Taro.getStorageSync('cookie')
    if (cookie) {
      method.config.headers['cookie'] = cookie
    }
    if (method.meta.loading) {
      _loading()
    }
    // 设置请求头
    if (!method.config.headers) {
      method.config.headers = {
        'X-Requested-With': 'Hiwie-Fetch',
        cookie
      };
    }
    // 添加token到请求头
    const token = useTokenStore.getState().token;
    if (token) {
      method.config.headers['D-Y-AUTH-TOKEN'] = token;
    }
    method.config.headers['Content-Type'] = 'application/json;charset=UTF-8';

    // 这里处理重复请求的问题。
    if ((method.type === 'POST' || method.type === 'PUT' || method.type === 'GET') && !excludeList.includes(method.url)) {
      const requestObj = {
        url: method.url,
        data: typeof method.data === 'object' ? JSON.stringify(method.data) : JSON.stringify(method.config.params),
        time: new Date().getTime(),
      }
      const sessionObj = await utils.$sessionCache().session.getJSON('sessionObj')
      if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
        utils.$sessionCache().session.setJSON('sessionObj', requestObj)
      } else {
        const s_data = sessionObj.data // 请求数据
        const s_url = sessionObj.url // 请求地址
        const s_time = sessionObj.time // 请求时间
        const interval = 500 // 间隔时间(ms)，小于此时间视为重复提交
        if (
          requestObj.time - s_time < interval &&
          s_url === requestObj.url && s_data === requestObj.data
        ) {
          const message = '数据正在处理，请勿重复提交'
          _showMsg(message, false)
          method.abort() // 中断请求
          return Promise.reject(new Error(message))
        } else {
          utils.$sessionCache().session.setJSON('sessionObj', requestObj)
        }
      }
    }

    // 判断参数是否空字符串，如果是则删除
    if (method.config.params) {
      Object.keys(method.config.params).forEach(key => {
        if (method.config.params[key] === '') {
          delete method.config.params[key]
        }
      })

    }
    if (method.data && typeof method.data === 'object') {
      const data = method.data;
      Object.keys(data).forEach(key => {
        if (data[key] === '') {
          delete data[key]
        }
      })
    }
  },
  async responded(response: any, method: any) {
    console.log(response.data,'=======')

    // 上传日志
    reportLog(response, method)
    if (method.url.includes('image/code')) {
      return response.data
    }

    if (response.header['Set-Cookie']) {
      const cookie = response.header['Set-Cookie']
      // 存储cookie
      Taro.setStorageSync('cookie', cookie);
    }

    if (response.data.hasOwnProperty('error')) {
      _hideLoading(method.meta)
      // 优先返回 error.parameters.error 中的内容，如果不存在则返回 error.message
      const errorMessage = response.data.error.parameters?.error || response.data.error.message || response.data.message;
      _showMsg(errorMessage, method.meta.isHideToastMsg)
      if (process.env.NODE_ENV === 'production') {
        logManager.info({
          url: method.url,
          params: response.data,
        })
      }
      // throw new Error(JSON.stringify(response));
      // 只抛出错误信息
      throw new Error(errorMessage);
    }


    // 处理401/403状态码
    if (response.statusCode === 401 || response.statusCode === 403) {
      _hideLoading(method.meta);
      // 清除本地数据
      Taro.clearStorageSync();
      Taro.showModal({
        title: '提示',
        content: '登录已过期，请重新登录',
        success: (res) => {
          if (res.confirm) {
            Taro.navigateTo({
              url: '/pages/userManage/login/index'
            })
          }
        }
      })
    }

    if (response.statusCode !== 200) {
      _hideLoading(method.meta)
      _showMsg(response.data.message, method.meta.isHideToastMsg)
      throw new Error(JSON.stringify(response));
    }
    // 检查响应格式
    if (response.data.hasOwnProperty('success')) {
      _hideLoading(method.meta)
      return response.data.success
    }

    // 如果 success 是一个对象，说明是正常的业务响应
    if (typeof response.data.success === 'object') {
      _hideLoading(method.meta)
      return response.data.success;
    }
    _hideLoading(method.meta)
    return response.data;
  },
});

class RequestHttp {
  post<T>(url, data, option: TMeta = { loading: true }) {
    console.log('post', url, data, option)
    // 确保 url 格式正确
    const apiUrl = url.startsWith('/') ? url.substring(1) : url;
    const methodInstance = alovaInst.Post<T>(apiUrl, data, {
      headers: baseConfig.headers,
      cacheFor: 0 // 禁用缓存
    })
    methodInstance.meta = {
      ...option,

    };
    return methodInstance
  }
  get<T>(url, params, option: TMeta = { loading: true }) {
    // 确保 url 格式正确
    const apiUrl = url.startsWith('/') ? url.substring(1) : url;
    const methodInstance = alovaInst.Get<T>(apiUrl, {
      params,
      headers: baseConfig.headers,
      cacheFor: 0 // 禁用缓存
    })
    methodInstance.meta = {
      ...option
    };
    return methodInstance
  }
  patch<T>(url, data, option: TMeta = { loading: true }) {
    // 确保 url 格式正确
    const apiUrl = url.startsWith('/') ? url.substring(1) : url;
    const methodInstance = alovaInst.Patch<T>(apiUrl, undefined, {
      params: data,
      headers: baseConfig.headers,
      cacheFor: 0 // 禁用缓存
    })
    methodInstance.meta = {
      ...option
    };
    return methodInstance
  }
  delete<T>(url, data, option: TMeta = { loading: true }) {
    // 确保 url 格式正确
    const apiUrl = url.startsWith('/') ? url.substring(1) : url;
    const methodInstance = alovaInst.Delete<T>(apiUrl,data, {
      headers: baseConfig.headers,
      cacheFor: 0 // 禁用缓存
    })
    methodInstance.meta = {
      ...option
    };
    return methodInstance
  }
  put<T>(url, data, option: TMeta = { loading: true }) {
    console.log('put', url, data, option)
    // 确保 url 格式正确
    const apiUrl = url.startsWith('/') ? url.substring(1) : url;
    const methodInstance = alovaInst.Put<T>(apiUrl, data, {
      headers: baseConfig.headers,
      cacheFor: 0 // 禁用缓存
    })
    methodInstance.meta = {
      ...option
    };
    console.log('methodInstance', methodInstance)
    return methodInstance.send()
  }
  // 上传图片
  upload<T>(url: string, params, option: TMeta = { loading: true }) {
    return new Promise<T>((resolve, reject) => {
      if (option.loading) {
        _loading()
      }
      let formData = {}
      if(params.jobNumber){
        formData = {
          path: params.path,
          jobNumber:params.jobNumber
        }
      }else{
        formData = {
          group: params.group,
        }
      }
      const token = Taro.getStorageSync('cookie')
      Taro.uploadFile({
        url: baseConfig.baseURL + url,
        filePath: params.file,
        formData: formData,
        header: {
          'cookie': token,
          'X-Requested-With': 'Hiwie-Fetch',
          'Content-Type': 'multipart/form-data',
        },

        name: 'file',

        success: (res) => {
          if (res.statusCode === 200) {
            const data = JSON.parse(res.data)
            resolve({
              url: data.success ? data.success : '',
            } as T)
          } else {
            _showMsg('上传失败', option.isHideToastMsg)
            reject(new Error(JSON.stringify(res)))
          }
        },
        fail: (err) => {
          _showMsg('上传失败', option.isHideToastMsg)
          reject(err)
        },
        complete: () => {
          if (option.loading) {
            _hideLoading(option)
          }
        }
      })
    })
  }
}

/**
 * 上报日志
 * @param response 响应
 * @param method 请求
 */
const reportLog = (response: any, method: any) => {
  if (!isProduction) {
    return
  }
  if (logManager) {
    const logData = {
      version,
      url: method.url,
      method: method.type,
      params: method.config.params,
      data: method.data,
      response: response.data,
      statusCode: response.statusCode,
    }
    // 警告的报错 - 401/403
    if (response.statusCode === 401 || response.statusCode === 403) {
      logManager.warn(logData)
    }
    // 错误信息的报错
    if (response.data.hasOwnProperty('error') || response.statusCode !== 200) {
      logManager.error(logData)
    }
  }
}

export default new RequestHttp();
